package org.hawk.gwt.ppc.reflect;

import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.HashSet;

import junit.framework.TestCase;

import org.hawk.gwt.ppc.javacc.JavaParserTreeConstants;
import org.hawk.gwt.ppc.javacc.JavaScanner;
import org.hawk.gwt.ppc.javacc.ParseException;
import org.hawk.gwt.ppc.reflect.mock.AnnotationMock;
import org.hawk.gwt.ppc.reflect.mock.EnumMock;
import org.hawk.gwt.ppc.reflect.mock.GenericClassMock;
import org.hawk.gwt.ppc.reflect.mock.GenericInterfaceMock;
import org.hawk.gwt.ppc.reflect.mock.Mock1;
import org.hawk.gwt.ppc.reflect.mock.Mock2;
import org.hawk.gwt.ppc.reflect.mock.Mock3;
import org.hawk.gwt.ppc.scanner.UniversalSourcesLoader;

public class MetadataTestCase extends TestCase {
	private static final String MOCK01 = "./src/org/hawk/gwt/ppc/reflect/mock/Mock1.java";
	private static final String MOCK02 = "./src/org/hawk/gwt/ppc/reflect/mock/Mock2.java";
	private static final String MOCK03 = "./src/org/hawk/gwt/ppc/reflect/mock/Mock3.java";
	private static final String MOCK04 = "./src/org/hawk/gwt/ppc/reflect/mock/AnnotationMock.java";
	private static final String MOCK05 = "./src/org/hawk/gwt/ppc/reflect/mock/EnumMock.java";
	private static final String MOCK06 = "./src/org/hawk/gwt/ppc/reflect/mock/GenericClassMock.java";
	private static final String MOCK07 = "./src/org/hawk/gwt/ppc/reflect/mock/GenericInterfaceMock.java";

	public void testNames() throws ParseException, IOException {
		MetadataProcessor processor1 = scan(MOCK01);
		assertEquals(Mock1.class.getName(), processor1.getClassName());
		MetadataProcessor processor2 = scan(MOCK02);
		assertEquals(Mock2.class.getName(), processor2.getClassName());
		MetadataProcessor processor3 = scan(MOCK03);
		assertEquals(Mock3.class.getName(), processor3.getClassName());
		MetadataProcessor processor4 = scan(MOCK04);
		assertEquals(AnnotationMock.class.getName(), processor4.getClassName());
		MetadataProcessor processor5 = scan(MOCK05);
		assertEquals(EnumMock.class.getName(), processor5.getClassName());
	}
	
	public void testImports() throws IOException, ParseException{
		MetadataProcessor processor = scan(MOCK01);
		assertEquals(new HashSet<String>(Arrays.asList(
				new String[]{"java.io.Serializable",
				"java.util.Map","com.google.gwt.core.client.EntryPoint"})),
			new HashSet<String>(processor.getImports(Mock1.class.getName())));
	}
	
	public void testGenericNames() throws ParseException, IOException {
		MetadataProcessor processor6 = scan(MOCK06);
		assertEquals(GenericClassMock.class.getName(), processor6.getClassName());
		MetadataProcessor processor7 = scan(MOCK07);
		assertEquals(GenericInterfaceMock.class.getName(), processor7.getClassName());
	}

	private MetadataProcessor scan(final String classToScan) throws ParseException,
			IOException {
		StringWriter stream = new StringWriter();
		MetadataProcessor processor = new MetadataProcessor(new UniversalSourcesLoader());
		JavaScanner scanner = new JavaScanner();
		scanner.addProcessor(JavaParserTreeConstants.JJTCOMPILATIONUNIT, processor);
		scanner.addProcessor(JavaParserTreeConstants.JJTCLASSORINTERFACEBODY, processor);
		scanner.addProcessor(JavaParserTreeConstants.JJTEXTENDSLIST, processor);
		scanner.addProcessor(JavaParserTreeConstants.JJTPACKAGEDECLARATION, processor);
		scanner.addProcessor(JavaParserTreeConstants.JJTIMPLEMENTSLIST, processor);
		scanner.addProcessor(JavaParserTreeConstants.JJTIMPORTDECLARATION, processor);
		scanner.addProcessor(JavaParserTreeConstants.JJTANNOTATIONTYPEBODY, processor);
		scanner.addProcessor(JavaParserTreeConstants.JJTENUMBODY, processor);
		
		scanner.startScan(new FileReader(classToScan),stream);
		
		return processor;
	}
}
